import createAxios from '/@/utils/axios'
import { useSiteConfig } from '/@/stores/siteConfig'
import { ElNotification, UploadRawFile } from 'element-plus'
import { randomNum, shortUuid } from '/@/utils/random'
import { fullUrl } from '/@/utils/common'
import { isAdminApp } from '/@/utils/common'
import OSS from 'ali-oss'

export const state = () => {
    const siteConfig = useSiteConfig()
    return siteConfig.upload.mode == 'local' ? 'disable' : 'enable'
}

export async function fileUpload(fd: FormData, params: anyObj = {}) {
    const siteConfig = useSiteConfig()
    if (siteConfig.upload.params.error !== 0) {
        if (siteConfig.upload.params.error === 2) {
            ElNotification({
                type: 'error',
                message: siteConfig.upload.params.data.code,
            })
        }
        if (siteConfig.upload.params.error === 1) {
            ElNotification({
                type: 'error',
                dangerouslyUseHTMLString: true,
                message: `
                    ${siteConfig.upload.params.data.code}<br/>
                    <a href="https://help.aliyun.com/document_detail/35028.html" target="_blank">点击查看错误说明</a>
                `,
            })
        }
        return false
    }
    const file = fd.get('file') as UploadRawFile
    const sha1 = await getFileSha1(file)
    const fileKey = getSaveName(file, sha1)
    delete params.uuid

    return new Promise(async (resolve, reject) => {
        const client = new OSS({
            // yourRegion填写Bucket所在地域。以华东1（杭州）为例，yourRegion填写为oss-cn-hangzhou。
            region: siteConfig.upload.params.region,
            // 从STS服务获取的临时访问密钥（AccessKey ID和AccessKey Secret）。
            accessKeyId: siteConfig.upload.params.accessKeyId,
            accessKeySecret: siteConfig.upload.params.accessKeySecret,
            // 从STS服务获取的安全令牌（SecurityToken）。
            stsToken: siteConfig.upload.params.securityToken,
            refreshSTSToken: async () => {
                const res = await createAxios(
                    {
                        url: isAdminApp() ? '/admin/Alioss/getSts' : '/api/Alioss/getSts',
                        method: 'get'
                    },
                    {
                        showCodeMessage: false,
                    }
                )
                return {
                    accessKeyId: res.data.params.accessKeyId,
                    accessKeySecret: res.data.params.accessKeySecret,
                    stsToken: res.data.params.securityToken
                }
            },
            refreshSTSTokenInterval: 3600 * 1000,
            bucket: siteConfig.upload.params.bucket,
            secure: true
        });

        client.put(fileKey, file).then(function (res:any) {
            const fileUrl = '/' + fileKey
            createAxios({
                url: isAdminApp() ? '/admin/Alioss/callback' : '/api/Alioss/callback',
                method: 'POST',
                data: {
                    url: fileUrl,
                    name: file.name,
                    size: file.size,
                    type: file.type,
                    sha1: sha1,
                }
            })
            resolve({
                code: 1,
                data: {
                    file: {
                        full_url: fullUrl(fileUrl),
                        url: fileUrl,
                    },
                },
                msg: res.error,
                time: Date.now(),
            })
        }).catch(function (err:any) {
            ElNotification({
                type: 'error',
                message: err,
            })
            reject({
                code: 0,
                data: {},
                msg: err,
                time: Date.now(),
            })
        })
    }) as ApiPromise
}

export function getSaveName(file: UploadRawFile, sha1: string) {
    const fileSuffix = file.name.substring(file.name.lastIndexOf('.') + 1)
    const fileName = file.name.substring(0, file.name.lastIndexOf('.'))
    const dateObj = new Date()

    const replaceArr: anyObj = {
        '{topic}': 'default',
        '{year}': dateObj.getFullYear(),
        '{mon}': ('0'+(dateObj.getMonth()+1)).slice(-2),
        '{day}': dateObj.getDate(),
        '{hour}': dateObj.getHours(),
        '{min}': dateObj.getMinutes(),
        '{sec}': dateObj.getSeconds(),
        '{random}': shortUuid(),
        '{random32}': randomNum(32, 32),
        '{filename}': fileName.substring(0, 100),
        '{suffix}': fileSuffix,
        '{.suffix}': '.' + fileSuffix,
        '{filesha1}': sha1,
    }
    const replaceKeys = Object.keys(replaceArr).join('|')
    const siteConfig = useSiteConfig()

    const savename = siteConfig.upload.savename[0] == '/' ? siteConfig.upload.savename.slice(1) : siteConfig.upload.savename

    return savename.replace(new RegExp(replaceKeys, 'gm'), (match) => {
        return replaceArr[match]
    })
}

async function getFileSha1(file: UploadRawFile) {
    const hashBuffer = await crypto.subtle.digest('SHA-1', await file.arrayBuffer())
    const hashArray = Array.from(new Uint8Array(hashBuffer))
    return hashArray.map((b) => b.toString(16).padStart(2, '0')).join('')
}
